/*
 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */


#ifndef _COMMON_SB_OPS_H
#define _COMMON_SB_OPS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>

#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/aes.h>
#include <openssl/err.h>
#include "common_rsa_keypair.h"
#include "common_crypto_asym.h"
#include "common_util_log.h"
#include "cc_crypto_defs.h"
#include "cc_pka_hw_plat_defs.h"

/* Global defines */
#define Nullptr (void *)0
#define SIZE_OF_DATA_FOR_DERIVATION 22

/**
 * @brief The SIGN_RELEASE releases the allocated memory from the sign operation.
 */

#define SIGN_RELEASE(fname) \
{\
    if (status < 0) \
        printf("\n%s failed.\n", fname); \
    if (pRsaPubKey) \
        RSA_free (pRsaPubKey); \
    if (bio) \
        BIO_free (bio); \
    if (md_ctx) \
        EVP_MD_CTX_destroy(md_ctx); \
    return (status); \
}

#define SIGN21_RELEASE(fname) \
{\
    if (status < 0) \
        printf("\n%s failed.\n", fname); \
    if (pRsaPrivKey) \
        RSA_free (pRsaPrivKey); \
    return (status); \
}
/**
 * @brief The RSA_LOADKEY_RELEASE releases the allocated memory from the loading key operation.
 */
#define RSA_LOADKEY_RELEASE(msg) \
{\
    if(status < 0) \
        printf("\n%s\n", msg); \
    if (rsa_pkey) \
        RSA_free (rsa_pkey); \
    if (out) \
        BIO_free (out); \
    return status; \
}

/**
 * @brief The CALCULATE_NP_RELEASE releases the allocated memory from the Np calculation operation.
 */
#define CALCULATE_NP_RELEASE(msg) \
{\
    if(status < 0) \
        printf("\n%s\n", msg); \
    if (N_Temp) \
        free(N_Temp); \
    if(NP_res) \
        free(NP_res); \
    BN_free (bn_r); \
    BN_free (bn_a); \
    BN_free (bn_p); \
    BN_free (bn_n); \
    BN_free (bn_quo); \
    BN_free (bn_rem); \
    return (status); \
}

/**
 * @brief The CALCULATE_H_RELEASE releases the allocated memory from the H calculation operation.
 */
#define CALCULATE_H_RELEASE(msg) \
{\
    if(status < 0) \
        printf("\n%s\n", msg); \
    if (N_Temp) \
        free(N_Temp); \
    if(H_res) \
        free(H_res); \
    if (H_resTemp) \
        OPENSSL_free(H_resTemp); \
    BN_free (bn_two); \
    BN_free (bn_twos); \
    BN_free (bn_n); \
    BN_free (bn_h); \
    return (status); \
}

#define MAX_IMAGE_CHUNK (1024)  // 1K byte

#ifdef USE_CONST_N
char N_Const[] =
{
    0x64, 0x39, 0x34, 0x38, 0x36, 0x66, 0x65, 0x34, 0x38, 0x64, 0x62, 0x34, 0x32, 0x34, 0x32, 0x36,
    0x62, 0x38, 0x64, 0x37, 0x37, 0x65, 0x62, 0x30, 0x30, 0x34, 0x33, 0x61, 0x35, 0x30, 0x37, 0x38,
    0x35, 0x61, 0x38, 0x65, 0x64, 0x31, 0x39, 0x36, 0x31, 0x36, 0x66, 0x38, 0x33, 0x33, 0x62, 0x63,
    0x36, 0x37, 0x65, 0x32, 0x62, 0x36, 0x37, 0x35, 0x33, 0x66, 0x64, 0x35, 0x32, 0x33, 0x62, 0x38,
    0x32, 0x62, 0x32, 0x64, 0x31, 0x37, 0x32, 0x65, 0x66, 0x64, 0x32, 0x34, 0x30, 0x34, 0x62, 0x33,
    0x65, 0x39, 0x30, 0x63, 0x31, 0x33, 0x39, 0x37, 0x65, 0x66, 0x66, 0x32, 0x64, 0x63, 0x61, 0x34,
    0x33, 0x61, 0x66, 0x64, 0x66, 0x35, 0x35, 0x61, 0x38, 0x36, 0x63, 0x32, 0x33, 0x63, 0x65, 0x37,
    0x64, 0x37, 0x32, 0x30, 0x36, 0x38, 0x38, 0x34, 0x66, 0x35, 0x33, 0x63, 0x38, 0x30, 0x62, 0x37,
    0x39, 0x30, 0x37, 0x38, 0x38, 0x63, 0x33, 0x63, 0x38, 0x61, 0x36, 0x38, 0x32, 0x34, 0x38, 0x64,
    0x39, 0x39, 0x37, 0x38, 0x30, 0x37, 0x63, 0x31, 0x61, 0x64, 0x39, 0x39, 0x31, 0x37, 0x31, 0x32,
    0x37, 0x38, 0x33, 0x64, 0x37, 0x38, 0x35, 0x65, 0x61, 0x37, 0x39, 0x64, 0x66, 0x36, 0x35, 0x31,
    0x32, 0x61, 0x64, 0x32, 0x37, 0x35, 0x31, 0x34, 0x38, 0x35, 0x31, 0x36, 0x62, 0x34, 0x36, 0x36,
    0x30, 0x35, 0x31, 0x31, 0x38, 0x64, 0x33, 0x33, 0x36, 0x35, 0x38, 0x61, 0x62, 0x38, 0x37, 0x38,
    0x66, 0x30, 0x34, 0x35, 0x32, 0x36, 0x66, 0x66, 0x62, 0x64, 0x65, 0x61, 0x32, 0x31, 0x39, 0x65,
    0x34, 0x33, 0x35, 0x66, 0x36, 0x61, 0x37, 0x32, 0x65, 0x65, 0x62, 0x31, 0x64, 0x32, 0x36, 0x64,
    0x64, 0x63, 0x31, 0x62, 0x33, 0x30, 0x35, 0x30, 0x61, 0x34, 0x38, 0x66, 0x36, 0x36, 0x65, 0x64,
    0x33, 0x33, 0x65, 0x31, 0x35, 0x62, 0x34, 0x34, 0x33, 0x64, 0x32, 0x63, 0x38, 0x61, 0x63, 0x65,
    0x35, 0x35, 0x62, 0x33, 0x63, 0x33, 0x63, 0x64, 0x62, 0x64, 0x62, 0x31, 0x63, 0x62, 0x63, 0x66,
    0x32, 0x63, 0x64, 0x32, 0x61, 0x63, 0x32, 0x61, 0x35, 0x32, 0x63, 0x64, 0x38, 0x34, 0x65, 0x34,
    0x62, 0x34, 0x31, 0x35, 0x36, 0x38, 0x61, 0x35, 0x63, 0x66, 0x66, 0x62, 0x63, 0x30, 0x63, 0x37,
    0x30, 0x36, 0x36, 0x38, 0x32, 0x31, 0x33, 0x61, 0x65, 0x34, 0x33, 0x64, 0x38, 0x34, 0x62, 0x38,
    0x61, 0x38, 0x33, 0x39, 0x35, 0x36, 0x66, 0x36, 0x37, 0x62, 0x64, 0x31, 0x62, 0x32, 0x62, 0x62,
    0x34, 0x38, 0x38, 0x38, 0x34, 0x65, 0x34, 0x65, 0x36, 0x38, 0x36, 0x30, 0x39, 0x33, 0x30, 0x66,
    0x63, 0x66, 0x66, 0x36, 0x33, 0x34, 0x61, 0x64, 0x39, 0x34, 0x64, 0x37, 0x30, 0x32, 0x36, 0x63,
    0x34, 0x66, 0x34, 0x64, 0x35, 0x63, 0x36, 0x32, 0x65, 0x31, 0x66, 0x37, 0x66, 0x31, 0x33, 0x32,
    0x61, 0x65, 0x61, 0x33, 0x65, 0x64, 0x61, 0x62, 0x37, 0x63, 0x39, 0x63, 0x62, 0x62, 0x64, 0x63,
    0x31, 0x31, 0x39, 0x66, 0x64, 0x66, 0x61, 0x39, 0x65, 0x39, 0x64, 0x38, 0x37, 0x63, 0x65, 0x37,
    0x36, 0x31, 0x34, 0x32, 0x65, 0x37, 0x65, 0x33, 0x38, 0x66, 0x35, 0x31, 0x32, 0x62, 0x63, 0x31,
    0x35, 0x62, 0x62, 0x34, 0x35, 0x33, 0x37, 0x62, 0x39, 0x62, 0x65, 0x37, 0x64, 0x32, 0x61, 0x32,
    0x36, 0x32, 0x30, 0x65, 0x36, 0x39, 0x35, 0x36, 0x65, 0x37, 0x35, 0x39, 0x66, 0x66, 0x38, 0x66,
    0x65, 0x34, 0x64, 0x37, 0x31, 0x65, 0x65, 0x66, 0x36, 0x31, 0x32, 0x39, 0x64, 0x64, 0x39, 0x36,
    0x38, 0x61, 0x62, 0x30, 0x30, 0x64, 0x31, 0x65, 0x64, 0x39, 0x63, 0x31, 0x39, 0x37, 0x30, 0x35
};
#endif

/**
 * @brief The Sign_v15 generates RSA signature using PKCS#1 v1.5 algorithm.
 *
 * The function
 * 1. Create RSA signature
 * 2. Verify the signature correctness
 * @param[in] pRsaPrivKey - the private key
 * @param[in] DataIn_ptr - the data to sign on
 * @param[in] DataInSize - the data size
 * @param[in] Key_ptr - passphrase string
 * @param[out] Signature_ptr - the RSA signature
 *
 */
 /*********************************************************/
int Sign_v15(RSA *pRsaPrivKey, char *DataIn_ptr,  // IG - merge with common implementation
             int DataInSize, char *Signature_ptr,
             char *Key_ptr);

/**
 * @brief The Sign_v21 generates RSA signature using PKCS#1 v2.1 algorithm.
 *
 * The function
 * 1. Create RSA signature
 * 2. Verify the signature correctness
 * @param[in] pRsaPrivKey - the private key
 * @param[in] DataIn_ptr - the data to sign on
 * @param[in] DataInSize - the data size
 * @param[out] Signature_ptr - the RSA signature
 *
 */
 /*********************************************************/
int Sign_v21(RSA *pRsaPrivKey, char *DataIn_ptr,
             int DataInSize, char *Signature_ptr);

/**
* @brief The function SBU_GetNFromKeyPairAndCalcH Reads RSA key from the file using passphrase,
*       and returns its decrypted value and its calculated Hash
*
* @param[in] PemEncryptedFileName_ptr - file name
* @param[in] pwdFileName - file name of the password
* @param[out] PemDecryted - N buffer
* @param[out] H_ptr - The H result. H size is N_SIZE_IN_BYTES*2 + 1
*
*/
/*********************************************************/
SBUEXPORT_C int SBU_GetNFromKeyPairAndCalcH(char* PemEncryptedFileName_ptr, char *pwdFileName, char *N_ptr, char *H_ptr);

/**
* @brief The SBU_RAND_Bytes reads RSA key from the file using passphrase
*        and returns its decrypted value.
*
* @param[in] PemEncryptedFileName_ptr - file name
* @param[in] Key_ptr - passphrase
*/
/*********************************************************/
SBUEXPORT_C int SBU_RAND_Bytes(int numBytes, char *buf);

/**
* @brief Reads RSA key from the file using passphrase, and returns its decrypted value and its Np
*
* @param[in] PemEncryptedFileName_ptr - file name
* @param[in] pwdFileName - file name of the password
* @param[out] PemDecryted - N and Np buffer
*/
/*********************************************************/
SBUEXPORT_C int SBU_GetNAndNpFromKeyPair(char* PemEncryptedFileName_ptr, char *pwdFileName, char *PemDecryted);

/**
* @brief Reads RSA key from the file using passphrase, and returns its decrypted value and its Np
*
* @param[in] PemEncryptedFileName_ptr - public key file name
* @param[out] PemDecryted - N and Np buffer
*/
/*********************************************************/
SBUEXPORT_C int SBU_GetNAndNpFromPubKey(char* PemEncryptedFileName_ptr, char *PemDecryted);

/**
* @brief Reads RSA public key from the file and returns its raw value and its Np
*
* @param[in] pPemFileName_ptr - file name
* @param[out] pNAndNp - N and Np buffer
*/
/*********************************************************/
SBUEXPORT_C int SBU_GetHashOfNAndNpFromPubKey(char* pPemFileName_ptr, char *pHash, int hashSize);




#endif
